Skip to content

Introduce AutoMonitor for simpler enablement of Application Signals #297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 64 commits into from

Conversation

sky333999
Copy link
Contributor

@sky333999 sky333999 commented Mar 24, 2025

Description of changes: Introduce Auto Monitor for Application Signals on K8s which provides an easier onboarding experience. When enabled, the Operator can auto-instrument K8s workloads that are associated with K8s services as they come up automatically without requiring explicit opt-in via workload specific annotations.

The operator now accepts a new arg auto-monitor-config that has the following structure:

{
  "monitorAllServices": false,
  "languages": [],
  "restartPods": false,
  "customSelector": {
    "java": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "python": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "dotnet": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "nodejs": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    }
  },
  "exclude": {
    "java": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "python": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "dotnet": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    },
    "nodejs": {
      "namespaces": [], "deployments": [], "daemonsets": [], "statefulsets": []
    }
  }
}
  • monitorAllServices: Enable AutoMonitor for all services in the cluster i.e. for any K8s workloads that are brought up in the cluster, auto-instrument them. Defaults to false i.e. not enabled.
  • langugages: Specify the list of languages that AutoMonitor should inject auto-instrumentation for. Defaults to all supported languages.
  • restartPods: When enabled, restart pods that are already running on the cluster corresponding to K8s workloads that now fall under the scope of AutoMonitor. Defaults to false i.e. not enabled.
  • customSelector: Provides more granular control to explicitly specify namespaces and workloads that should be auto-instrumented. Can be specified even if monitorAllServices is disabled.
  • exclude: Similar to customSelector, but is instead used to deny specific namespaces or workloads from getting auto-instrumented when monitorAllServices is enabled. Takes precedence over customSelector in the case of conflicts.

Additional Notes:

  • customSelector with restartPods enabled serves as a replacement for the existing auto-annotation-config arg. auto-annotation-config will be deprecated entirely in a future release. Using both is consider invalid and will continue to respect auto-annotation-config in such scenarios.
  • monitorAllServices by default does not auto-instrument services in the kube-system and amazon-cloudwatch namespaces. If you require services in these namespaces to be auto-instrumented, you can explicitly specify them using customSelector.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@the-mann the-mann marked this pull request as ready for review May 7, 2025 20:51
main.go Outdated
if err := json.Unmarshal([]byte(autoAnnotationConfigStr), &autoAnnotationConfig); err != nil {
setupLog.Error(err, "Unable to unmarshal auto-annotation config")
} else {
// todo: technically a breaking change, because previously an empty autoAnnotationConfig would clear all annotations, but automonitor does not reproduce this behavior by default because it requires restartPods to be enabled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I don't think we need this todo here. We expect this and aligned that this is expected. We aren't going to have "parity" by clearing all annotations when restartPods is false.

main.go Outdated
if os.Getenv("DISABLE_AUTO_ANNOTATION") == "true" {
setupLog.Info("Auto-annotation is disabled")
} else if autoAnnotationConfigStr != "" {
if err := json.Unmarshal([]byte(autoAnnotationConfigStr), &autoAnnotationConfig); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if an auto annotation config exists, and we are unable to marshal shouldn't we just return the error here? Why keep going?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because we might want to use AutoMonitor instead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i could go either way on this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I'm thinking if a customer has an auto annotation config -- the intention is to use auto annotation and if that fails we should just return an error. But not a big deal

@the-mann the-mann force-pushed the mpmann/appsignals-1-step branch from ef66e90 to 0e27206 Compare May 8, 2025 19:42
lisguo
lisguo previously approved these changes May 8, 2025
main.go Outdated
if os.Getenv("DISABLE_AUTO_ANNOTATION") == "true" {
setupLog.Info("Auto-annotation is disabled")
} else if autoAnnotationConfigStr != "" {
if err := json.Unmarshal([]byte(autoAnnotationConfigStr), &autoAnnotationConfig); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I'm thinking if a customer has an auto annotation config -- the intention is to use auto annotation and if that fails we should just return an error. But not a big deal

assert.NotNil(t, annotator, "Expected non-nil annotator")

// Check type using type assertion
actualType := fmt.Sprintf("%T", annotator)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Would prefer to use reflection or some enum that checks the actual type instead of these string representations. If we ever rename the struct or package or move it to a different package, these tests will break.

Could do something like

expectedType: reflect.TypeOf(auto.AnnotationMutators{})

...

assert.Equals(t, tt.expectedType, reflect.TypeOf(annotator))

or

type annotatorType int

const (
	unset annotatorType = iota
	mutators
	monitor
)

...

switch annotator.(type) {
case *auto.AnnotationMutators:
  assert.Equals(t, mutators, tt.expectedType)
}

}

if autoAnnotationConfigStr == "" {
return nil, fmt.Errorf("auto-annotation configuration not provided, disabling AutoAnnotation")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this get logged as an error when the environment variable case is logged as an info message? This seems like a common case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that this probably doesnt need to be an error.
But dont think this will be very common since our add-on/chart will set the default for this as the java: {deployments:[], ...} string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we do the same below for autoAnnotationConfig.Empty() and that will be true.

return typesSelected
}

func (c AnnotationConfig) Empty() bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super minor nit: Naming might suggest that it would empty the configuration.

Suggested change
func (c AnnotationConfig) Empty() bool {
func (c AnnotationConfig) IsEmpty() bool {

@sky333999 sky333999 changed the title AutoMonitor Introduce AutoMonitor for simpler enablement of Application Signals May 8, 2025
@the-mann
Copy link
Contributor

the-mann commented May 9, 2025

/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants